/**
 * @file common/ducks/io.js IO库封装
 * @author zhanlong
 */

/* eslint-disable */
import u from 'underscore';
import React from 'react';
import _fetch from 'isomorphic-fetch';
import {Modal} from 'antd';
import {getCookie} from './common'

import {isBrowser} from './common';

let isGlobalModalVisible = false;
function showGlobalError(content, title = '错误提示', path) {
    if (isBrowser() && !isGlobalModalVisible) {
        isGlobalModalVisible = true;
        Modal.error({
            title,
            content: <div dangerouslySetInnerHTML={{__html: content}} />,
            onOk() {
                isGlobalModalVisible = false;
                !path ? location.pathname = '/' : '';
            }
        });
    }
}

function fetch(url, options = {}, ctxCookie, headersOptions = {}) {

    const headers = {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Content-Type': 'application/json',
        'mode': 'cors',
        'Authorization': `Bearer ${getCookie('token')}`,
        ...headersOptions
    };

    if (!isBrowser() && ctxCookie) {
        headers.cookie = ctxCookie;
    }

    return _fetch(url,  {credentials: 'include', headers, ...options})
        .then(res => {
            let result;

            return res.json().then(data => {
                result = data;
                if (res.status > 400 || res.status < 200 || data.result === 1) {
                    result = Promise.reject(data);
                }

                return result;
            })
            .catch(ex => {
                let result;

                if (res.headers.get('content-length') == 0) {
                    result = Promise.resolve({});
                }
                else {
                    isBrowser() && showGlobalError(ex.message);
                    result = Promise.reject(ex);
                }

                return result;
            });
        })
        .catch(ex => {
            ex = u.isObject(ex) ? ex : {code: 'NETWORK_ERR', message: ex};

            showGlobalError(ex.message);

            return Promise.reject(ex);
        });
}

function stringify(obj) {
    if (obj === null || !obj) {
        return '';
    }

    let search = '';

    /* eslint-disable */
    for (let key in obj) {
        let val = obj[key];

        if (Object.hasOwnProperty.call(obj, key)) {
            key = encodeURIComponent(key);

            if (val == undefined) {
                continue;
            }
            else if (typeof val === 'Array') {
                search += `${key}=`;
                val.map(item => search += `${item},`);
                search = search.replace(/,$/, '&');
            }

            else if (val === true) {
                search += `${key}&`;
            }

            else {
                val = encodeURIComponent(val);
                search += `${key}=${val}&`;
            }
        }

    }
    /* eslint-enable */

    search = search.replace(/&$/, '');

    return search;
}

function _get(url, query = {}, ctxCookie, headersOptions = {}) {
    let params = stringify(query);

    if (params) {
        url = url.indexOf('?') > -1 ? `${url}${params}` : `${url}?${params}`;
    }

    return fetch(url, {method: 'get'}, ctxCookie, headersOptions);
}

function _post(url, query = {}, ctxCookie, headersOptions = {}) {
    return fetch(url, {
        method: 'post',
        body: JSON.stringify(query)
    }, ctxCookie, headersOptions);
}

function _put(url, query = {}, ctxCookie, headersOptions = {}) {
    return fetch(url, {
        method: 'put',
        body: JSON.stringify(query)
    }, ctxCookie, headersOptions);
}

function _delete(url, query = {}, ctxCookie, headersOptions = {}) {
    return fetch(url, {
        method: 'delete',
        body: JSON.stringify(query)
    }, ctxCookie, headersOptions);
}

function _rawPost(url, query = {}, ctxCookie) {
    return _fetch(url, {
        method: 'post',
        body: JSON.stringify(query)
    }, ctxCookie);
}

export default {
    showGlobalError,
    stringify,
    get: _get,
    post: _post,
    put: _put,
    delete: _delete,
    rawPost: _rawPost
};
